home *** CD-ROM | disk | FTP | other *** search
- /* NOTE: because of size, the previous 'mailbox.c' has been
- * split in 3 parts:
- * mboxcmd.c, containing the 'mbox' subcommands,
- * mailbox.c, containing some user mailbox commands, and
- * mailbox2.c, containing the remaining user commands.
- * 921125 - WG7J
- */
- /* There are only two functions in this mailbox code that depend on the
- * underlying protocol, namely mbx_getname() and dochat(). All the other
- * functions can hopefully be used without modification on other stream
- * oriented protocols than AX.25 or NET/ROM.
- *
- * SM0RGV 890506, most work done previously by W9NK
- *
- *** Changed 900114 by KA9Q to use newline mapping features in stream socket
- * interface code; everything here uses C eol convention (\n)
- *
- * Numerous new commands and other changes by SM0RGV, 900120
- *
- * Gateway function now support outgoing connects with the user's call
- * with inverted ssid. Users can connect to system alias as well...
- * See also several mods in socket.c,ax25.c and others
- * 11/15/91, WG7J/PA3DIS
- *
- * Userlogging, RM,VM and KM commands, and R:-line interpretation
- * added 920307 and later, Johan. K. Reinalda, WG7J/PA3DIS
- *
- * Inactivity timeout-disconnect added 920325 and later - WG7J
- *
- * mbxrecvline() now can gobble up suboptions - 94/02/14 VE4WTS
- */
- #include <stdio.h>
- #include <time.h>
- #include <ctype.h>
- #ifdef MSDOS
- #include <alloc.h>
- #endif
- #include <stdlib.h>
- #include <string.h>
- #ifdef UNIX
- #include <sys/types.h>
- #include <sys/stat.h>
- #endif
- #include "global.h"
- #include "config.h"
- #include "timer.h"
- #include "proc.h"
- #include "socket.h"
- #include "usock.h"
- #include "session.h"
- #include "smtp.h"
- #include "dirutil.h"
- #include "telnet.h"
- #include "ftp.h"
- #include "ftpserv.h"
- #include "commands.h"
- #include "netuser.h"
- #include "files.h"
- #include "bm.h"
- #include "pktdrvr.h"
- #include "ax25.h"
- #include "mailbox.h"
- #include "ax25mail.h"
- #include "nr4mail.h"
- #include "cmdparse.h"
- #include "mailfor.h"
-
- #ifdef MAILBOX
-
- /* Log all gateway connects to the logfile - WG7J */
- #define GWTRACE 1
-
- /* By setting the fp to NULL, we can check in exitbbs()
- * wether a tempfile has been closed or not - WG7J
- */
- #define MYFCLOSE(x) { fclose(x); x = (FILE *) 0; }
-
- /*
- #define MBDEBUG
- */
-
- extern time_t StartTime;
- extern char Myalias[];
-
- struct mbx *Mbox;
- int BbsUsers;
- int Totallogins;
- extern char *Mtmsg;
- extern int MAttended;
- extern unsigned Maxlet;
- extern char Mbpasswd[];
-
- extern char Noperm[];
- extern char Nosock[];
- extern char MboxId[];
-
- char Loginbanner[] = "\nKA9Q NOS (%s)\n\n";
- char Mbwelcome[] = "\nWelcome %s,\n";
- char Mbbanner[] = "to the %s TCP/IP Mailbox (%s)\n";
- char CurUsers[] = "Currently %d user(s)\n";
- char Howtoend[] = "End with /EX or ^Z in first column (^A aborts):\n";
- char MsgAborted[] = "Msg aborted\n";
-
- #ifdef MAILCMDS
- char CcLine[] = "Cc: ";
- char Mbwarning[] = "Third Party mail is not permitted.\n";
- int MbSent;
- int MbRead;
- int MbRecvd;
- #ifdef MBFWD
- int MbForwarded;
- #endif
- #endif
-
- char Mbmenu[] = "Current msg# %d.\n?,"
- #ifdef MAILCMDS
- "A,"
- #endif
- "B,C,D,E,F,H,I,IH,IP,J,K,"
- #ifdef MAILCMDS
- "L,"
- #endif
- "M,"
- #ifdef NETROM
- "N,NR,"
- #endif
- "O,P,"
- #ifdef CALLCLI
- "Q,"
- #endif
- #ifdef MAILCMDS
- "R,S,"
- #endif
- "T,U,"
- #ifdef MAILCMDS
- "V,"
- #endif
- "W,X,Z >\n";
-
- extern char Mbnrid[];
-
- #ifdef MAILCMDS
- #ifdef NETROM
- #ifdef CALLCLI
- char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger\n"
- "H)elp I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers\n"
- "N)odes O)perator P)orts Q)uery R)ead S)end T)elnet\n"
- "U)pload V)erbose W)hat X)pert Z)ap\n";
- #else
- char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger\n"
- "H)elp I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers\n"
- "N)odes O)perator P)orts R)ead S)end T)elnet\n"
- "U)pload V)erbose W)hat X)pert Z)ap\n";
- #endif /*CALLCLI*/
- #else /*NETROM*/
- #ifdef CALLCLI
- char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger H)elp\n"
- "I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers O)perator\n"
- "P)orts Q)uery R)ead S)end T)elnet U)pload V)erbose\n"
- "W)hat X)pert Z)ap\n";
-
- #else
- char Longmenu[] = "?)help A)rea B)ye C)onnect D)wnload E)scape F)inger H)elp\n"
- "I)nfo IH)eard IP)route J)heard K)ill L)ist M)boxusers O)perator P)orts\n"
- "R)ead S)end T)elnet U)pload V)erbose W)hat X)pert Z)ap\n";
- #endif /*CALLCLI*/
- #endif /*NETROM*/
- #else /* MAILCMDS */
- #ifdef NETROM
- #ifdef CALLCLI
- char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
- "IP)route J)heard M)boxusers N)odes O)perator P)orts Q)uery T)elnet\n"
- "U)pload W)hat X)pert Z)ap\n";
- #else
- char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
- "IP)route J)heard M)boxusers N)odes O)perator P)orts T)elnet U)pload W)hat\n"
- "X)pert Z)ap\n";
- #endif /*CALLCLI*/
- #else /*NETROM*/
- #ifdef CALLCLI
- char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
- "IP)route J)heard M)boxusers O)perator P)orts Q)uery T)elnet U)pload W)hat\n"
- "X)pert Z)ap\n";
-
- #else
- char Longmenu[] = "?)help B)ye C)onnect D)wnload E)scape F)inger H)elp I)nfo IH)eard\n"
- "IP)route J)heard M)boxusers O)perator P)orts T)elnet U)pload W)hat X)pert Z)ap\n";
- #endif /*CALLCLI*/
- #endif /*NETROM*/
- #endif /* MAILCMDS */
-
- extern int dombusers __ARGS((int argc,char *argv[],void *p));
- extern int dombpast __ARGS((int argc,char *argv[],void *p));
- extern int doarea __ARGS((int argc,char *argv[],void *p));
- extern int dombstatus __ARGS((int argc,char *argv[],void *p));
- extern int dombmailstats __ARGS((int argc,char *argv[],void *p));
- void mboxredundant __ARGS((struct mbx *m));
- #ifdef CALLCLI
- static int dombcallbook __ARGS((int argc,char *argv[],void *p));
- #endif
- extern int doipheard __ARGS((int argc,char *argv[],void *p));
- static int mbx_getname __ARGS((struct mbx *m));
- static int dochat __ARGS((int argc,char *argv[],void *p));
-
-
- extern int Mbnewmail;
- extern int Usenrid;
- extern int MBSecure;
- extern int Mbsendquery;
- #ifdef MBXTDISC
- extern int32 Mbtdiscinit;
- #endif
-
- int
- dombports(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp;
- struct mbx *m = (struct mbx *)p;
-
- tputs("Available ports:\n");
- for(ifp=Ifaces;ifp!=NULLIF;ifp=ifp->next)
- if(ifp->type == CL_AX25 && \
- (!(ifp->flags & HIDE_PORT) || (m->privs & SYSOP_CMD)) ) {
- tprintf("%-7s",ifp->name);
- if(ifp->descr != NULLCHAR)
- tprintf(": %s",ifp->descr);
- else
- tputc('\n');
- }
- tputc('\n');
- return 0;
- }
-
- /* This is called by the finger-daemon */
- void
- listusers(s)
- int s;
- {
- int outsave;
- struct mbx m;
-
- m.privs = 0;
- m.stype = ' ';
-
- #ifdef notdef
- usprintf(s,"\nCurrent remote users:\n");
- #endif
- outsave = Curproc->output;
- Curproc->output = s;
- dombusers(0,NULLCHARP,&m);
- Curproc->output = outsave;
- }
-
- struct mbx *
- newmbx()
- {
- struct mbx *m,*new;
-
- if((new = (struct mbx *) callocw(1,sizeof(struct mbx))) == NULLMBX)
- return NULLMBX;
- BbsUsers++;
- /* add it into the list */
- if((m=Mbox) == NULLMBX)
- Mbox = new;
- else {
- while(m->next)
- m=m->next;
- m->next = new;
- }
- return new;
- }
-
- static int
- mbx_getname(m)
- struct mbx *m;
- {
- char *cp;
- FILE *tfp;
- union sp sp;
- char tmp[MAXSOCKSIZE];
- int len = MAXSOCKSIZE;
- int anony = 0;
- int oldmode;
- int founddigit=0;
- int count=0;
- #ifdef AX25
- int32 flags;
- int ax_25 = 0;
- struct usock *up;
- #endif
-
- sp.p = tmp;
- sp.sa->sa_family = AF_LOCAL; /* default to AF_LOCAL */
- getpeername(m->user,tmp,&len);
- m->family = sp.sa->sa_family;
- m->path = mallocw(MBXLINE);
- /* This is one of the two parts of the mbox code that depends on the
- * underlying protocol. We have to figure out the name of the
- * calling station. This is only practical when AX.25 or NET/ROM is
- * used. Telnet users have to identify themselves by a login procedure.
- */
- #ifdef __GNUC__
- flags = 0; /* silence "uninitialized" warning */
- #endif
- switch(sp.sa->sa_family){
- #ifdef AX25
- case AF_AX25:
- /* If this is not to the convers call, and this port is
- * set for NO_AX25, then disconnect ! - WG7J
- */
- if((m->type != CONF_LINK) && ((up = itop(m->user)) != NULLUSOCK) ) {
- if((flags=up->cb.ax25->iface->flags) & NO_AX25)
- return -1;
- }
- ax_25 = 1;
- /* note fallthrough */
- case AF_NETROM:
- /* NETROM and AX25 socket address structures are "compatible" */
- /* Save user call, in case user wants to use gateway function */
- memcpy(m->call,sp.ax->ax25_addr,AXALEN);
- m->call[ALEN] &= 0xfc;/*Make sure E-bit isn't set !*/
- pax25(m->name,sp.ax->ax25_addr);
- cp = strchr(m->name,'-');
- if(cp != NULLCHAR) /* get rid of SSID */
- *cp = '\0';
- /* SMTP wants the name to be in lower case */
- cp = m->name;
- while(*cp){
- if(isupper(*cp))
- *cp = tolower(*cp);
- ++cp;
- }
- anony = 1;
- /* Try to find the privileges of this user from the userfile */
- if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony)) == -1){
- m->privs = 0;
- free(m->path);
- m->path = NULLCHAR;
- }
- if(m->privs & EXCLUDED_CMD)
- return -1;
- if(ax_25)
- if(((flags & USERS_ONLY) && (m->privs & IS_BBS)) ||
- ((flags & BBS_ONLY) && !(m->privs & IS_BBS)) ||
- ((flags & SYSOP_ONLY) && !(m->privs & SYSOP_CMD)))
- return -1;
- return 0;
- #endif
- case AF_LOCAL:
- case AF_INET:
- m->state = MBX_LOGIN;
- tprintf(Loginbanner,Hostname);
- if(Mtmsg != NULLCHAR)
- tputs(Mtmsg);
- for(;;){
- /* Maximum of 3 tries - WG7J */
- if(count++ == 3)
- return -1;
- oldmode = sockmode(m->user,SOCK_ASCII);
- tputs("login: ");
- usflush(m->user);
- if(mbxrecvline(m) == -1)
- return -1;
- if(*m->line == 4) /* Control-d */
- return -1;
- if(*m->line == '\0')
- continue;
-
- /* add a little test to avoid 'Mailfile busy' syndrome - WG7J */
- if((cp=strchr(m->line,'.')) != NULLCHAR)
- *cp = '_';
- if((cp=strchr(m->line,'/')) != NULLCHAR)
- *cp = '_';
- if((cp=strchr(m->line,'\\')) != NULLCHAR)
- *cp = '_';
- if((tfp=fopen(m->line,"w")) == NULL) /* Invalid name */
- continue;
- fclose(tfp);
- unlink(m->line);
- if(strlen(m->line) < sizeof(m->name))
- strcpy(m->name,m->line);
- else /* Too long! */
- continue;
- tprintf("Password: %c%c%c",IAC,WILL,TN_ECHO);
- usflush(m->user);
- sockmode(m->user,SOCK_BINARY);
- if(mbxrecvline(m) == -1)
- return -1;
- tprintf("%c%c%c",IAC,WONT,TN_ECHO);
- sockmode(m->user,oldmode);
- tputc('\n');
- usflush(m->user);
- /* This is needed if the password was send before the
- * telnet no-echo options were receied. We neeed to
- * flush the eold sequence from the input buffers, sigh
- */
- if(socklen(m->user,0))/* discard any remaining input */
- recv_mbuf(m->user,NULL,0,NULLCHAR,0);
- if((m->privs = userlogin(m->name,m->line,&m->path,MBXLINE,&anony))
- != -1){
- if(anony)
- log(m->user,"MBOX login: %s Password: %s",m->name,m->line);
- else
- log(m->user,"MBOX login: %s",m->name);
- if(m->privs & EXCLUDED_CMD)
- return -1;
- #ifdef AX25
- /*try to set the name as the user-call.
- *this is a very crude test! Be careful...
- *Login must have at leat 1 digit (0-9) in it,
- *and it must be possible to convert it to a call.
- *if this doesn't work, disallow the gateway command,
- *no matter if this was allowed by priviledges or not.
- *Be careful, some one with login name '4us' and
- *permission set to allow gateway/netrom, will
- *go out as '4us-15' or '4us-0' !!!!!
- *11/15/91 WG7J/PA3DIS
- */
- for(cp=m->name;*cp != '\0';cp++)
- if(isdigit((int)*cp))
- break;
- if(*cp != '\0')
- founddigit = 1;
- if( (setcall(m->call,m->name) == -1) || (!founddigit) ) {
- m->privs &= ~AX25_CMD;
- m->privs &= ~NETROM_CMD;
- }
- #else
- m->privs &= ~AX25_CMD;
- m->privs &= ~NETROM_CMD;
-
- #endif /* AX25 */
- /* Set the morerows to MAXLIN for telnet logins - WG7J */
- m->morerows = MAXLIN - 1;
- return 0;
- }
- tputs("Login incorrect\n");
- log(m->user,"MBOX Login failed: %s, pw %s",m->name,m->line);
- mail_error("MBOX Login failed: %s, pw %s",m->name,m->line);
- *m->name = '\0'; /* wipe any garbage */
- }
- }
- return 0;
- }
-
- /* put up the prompt */
- void
- putprompt(m)
- struct mbx *m;
- {
- char area[64];
- char *cp1,*cp2;
-
- #ifdef MAILCMDS
- if(m->sid & MBX_SID)
- tputs(">\n");
- else {
- #endif
- if(m->sid & MBX_NRID)
- tputs(Mbnrid);
- #ifdef MAILCMDS
- if(m->sid & MBX_AREA) {
- cp1 = m->area;
- cp2 = area;
- /* Convert / and \ into . */
- while(*cp1 != '\0') {
- if(*cp1=='/')
- *cp2 = '.';
- else
- *cp2 = *cp1;
- cp1++;
- cp2++;
- }
- *cp2 = '\0';
- tprintf("Area: %s ",area);
- }
- #endif
- tprintf((m->sid & MBX_EXPERT) ? ">\n" : Mbmenu, m->current);
- #ifdef MAILCMDS
- }
- #endif
- }
-
- #ifdef MBXTDISC
- /* Mailbox user has been idle for too long,
- * disconnect the socket - WG7J
- */
- void
- #ifdef PROTOTYPES
- mboxredundant(struct mbx *m)
- #else
- mboxredundant(m)
- struct mbx *m;
- #endif
- {
- struct usock *up;
-
- /* nasty hack! we may have screwed up reference count */
- /* by invoking newproc("smtp_send",....); Fudge it! */
- if((up = itop(m->user)) != NULLUSOCK)
- up->refcnt = 1;
-
- /* Close the socket*/
- close_s(m->user);
- return; /* Keep lint happy */
- }
- #endif
-
-
- /* Incoming mailbox session */
- void
- mbx_incom(s,t,p)
- int s;
- void *t;
- void *p;
- {
- #ifdef TIPMAIL
- #ifdef XMODEM
- struct tipcb *tip;
- #endif
- #endif
- struct mbx *m,*mp,*pp;
- struct usock *up;
- char *buf[3];
- char tmp[AXBUF];
- int rval;
- FILE *fp;
-
- /*
- if((up = itop(s)) != NULLUSOCK)
- if(up->iface->flags & NO_AX25)
- */
-
- sockmode(s,SOCK_ASCII);
- sockowner(s,Curproc); /* We own it now */
- /* Secede from the parent's sockets, and use the network socket that
- * was passed to us for both input and output. The reference
- * count on this socket will still be 1; this allows the domboxbye()
- * command to work by closing that socket with a single call.
- * If we return, the socket will be closed automatically.
- */
- close_s(Curproc->output);
- close_s(Curproc->input);
- Curproc->output = Curproc->input = s;
-
- /* We'll do our own flushing right before we read input */
- setflush(s,-1);
-
- if((m = newmbx()) == NULLMBX){
- tputs("Too many mailbox sessions\n");
- return;
- }
-
- m->user = s;
- m->escape = 20; /* default escape character is Ctrl-T */
- m->linemode = 0;
- m->type = (int) t;
-
- #ifdef TIPMAIL
- #ifdef XMODEM
- if(m->type == TIP_LINK) {
- tip = (struct tipcb *) p;
- tip->raw=0;
- m->tip=tip;
- }
- #endif
- #endif
-
- /* discard any remaining input */
- /*
- while(socklen(s,0))
- recv_mbuf(s,NULL,0,NULLCHAR,0);
- */
-
- /* get the name of the remote station */
- if(mbx_getname(m) == -1) {
- exitbbs(m);
- return;
- }
- Totallogins++;
-
- #ifdef CONVERS
- if((int)t & CONF_LINK) {
- if(m->privs & NO_CONVERS) {
- tputs(Noperm);
- mail_error("%s: conv-call access denied\n",m->name);
- } else {
- m->state = MBX_CONVERS;
- chname(Curproc,"conference");
- log(s,"open CONF");
- mbox_converse(m);
- }
- /* now free it from list */
- for(mp=Mbox,pp=NULLMBX;mp!=m;pp=mp,mp=mp->next);
- if(pp==NULLMBX) /* first one on list */
- Mbox = m->next;
- else
- pp->next = m->next;
- free((char *)m);
- BbsUsers--;
- close_s(Curproc->output);
- return;
- }
- #endif
-
- #ifdef TTYCALL
- if((int)t & TTY_LINK) {
- int ostate = m->state;
-
- m->state = MBX_CHAT;
- chname(Curproc,"ttylink");
- log(s,"open TTYLINK");
- if (dochat(0, 0, m) == 2)
- {
- /* now free it from list */
- for(mp=Mbox,pp=NULLMBX;mp!=m;pp=mp,mp=mp->next);
- if(pp==NULLMBX) /* first one on list */
- Mbox = m->next;
- else
- pp->next = m->next;
- free((char *)m);
- BbsUsers--;
- close_s(Curproc->output);
- return;
- }
- tputs("Chaining to BBS...\n");
- m->state = ostate;
- }
- #endif
-
- log(s,"open MBOX");
- #ifdef MBXTDISC
- /*Start inactivity timer - WG7J */
- set_timer(&m->tdisc,Mbtdiscinit * 1000L);
- m->tdisc.func = (void(*)__FARGS((void*)))mboxredundant;
- m->tdisc.arg = m;
- start_timer(&m->tdisc);
- #endif
- if(m->privs & IS_BBS)
- m->sid = MBX_SID; /*force bbs status*/
- else
- if(m->privs & IS_EXPERT)
- m->sid |= MBX_EXPERT;
-
- loguser(m);
- m->state = MBX_CMD; /* start in command state */
- #ifdef MAILCMDS
- tputs(MboxId);
- #endif
-
- /* Say 'hello' only if user is not a bbs - WG7J */
- #ifdef MAILCMDS
- if(!(m->sid & MBX_SID)) {
- #endif
- tprintf(Mbwelcome,m->name);
- #ifdef AX25
- if(m->family == AF_INET)
- #endif
- tprintf(Mbbanner,Hostname,Version);
- #ifdef AX25
- else
- tprintf(Mbbanner,pax25(tmp,Mycall),Version);
- #endif
- /* How many users are there currently ? */
- tprintf(CurUsers,BbsUsers);
-
- #ifdef MAILCMDS
- /* Do we accept third party mail ? */
- if(!ThirdParty)
- tputs(Mbwarning);
- #endif
- tputc('\n');
-
- /* Is there a message of the day ? */
- if((fp = fopen(Motdfile,READ_TEXT)) != NULLFILE) {
- sendfile(fp,m->user,ASCII_TYPE,0);
- fclose(fp);
- }
-
- #ifdef MAILCMDS
- #ifdef USERLOG
- /* Tell about new arrived mail in message areas - WG7J */
- if(Mbnewmail)
- listnewmail(m);
- #endif
- #endif
-
- /* make sure user gets it */
- /* usflush(m->user); done in mbxrecvline() */
-
- #ifdef MAILCMDS
- /* Enable our local message area,
- * only if we're not a bbs - WG7J
- */
- buf[1] = m->name;
- doarea(2,buf,m);
- }
- #endif
-
- /* Send prompt */
- putprompt(m);
-
- while(mbxrecvline(m) != -1){
- if((rval = mbx_parse(m)) == -2)
- break;
- if(rval == 1)
- tputs("Bad syntax.\n");
- #ifdef notdef
- tprintf("last = %ld, new last = %ld\n",m->lastread,m->newlastread);
- #endif
- #ifdef MAILCMDS
- /* Only tell about new mail when in our own area - WG7J */
- if(!(m->sid & MBX_SID) && !strcmp(m->name,m->area) &&
- (isnewprivmail(m) > 0L) )
- tputs("You have new mail. Please Kill when read!\n");
- /* Do not check mailfile if we're bbs, saves a tmpfile- WG7J*/
- if(!(m->sid & MBX_SID))
- scanmail(m);
- #endif
- putprompt(m);
- m->state = MBX_CMD;
- }
- exitbbs(m);
-
- /* by invoking newproc("smtp_send",....); Fudge it! */
- if((up = itop(Curproc->output)) != NULLUSOCK)
- up->refcnt = 1;
- close_s(Curproc->output);
-
- }
-
- void
- exitbbs(m)
- struct mbx *m;
- {
- struct mbx *mp,*pp;
-
- #ifdef MBXTDISC
- stop_timer(&m->tdisc);
- #endif
- closenotes(m);
- free(m->to);
- free(m->tofrom);
- free(m->origto);
- free(m->origbbs);
- free(m->subject);
- free(m->date);
- free(m->tomsgid);
- free(m->path);
- /* Close the tempfiles if they are not nullpointers - WG7J */
- if(m->tfile != (FILE *) 0)
- fclose(m->tfile);
- if(m->tfp != (FILE *) 0)
- fclose(m->tfp);
- if(m->stdinbuf != NULLCHAR)
- free(m->stdinbuf);
- if(m->stdoutbuf != NULLCHAR)
- free(m->stdoutbuf);
- free((char *)m->mbox);
- /* now free it from list */
- for(mp=Mbox,pp=NULLMBX;mp && mp!=m;pp=mp,mp=mp->next);
- if(!mp)
- /* what happened ??? */
- return;
- if(pp==NULLMBX) /* first one on list */
- Mbox = Mbox->next;
- else
- pp->next = m->next;
- free((char *)m);
- BbsUsers--;
- }
-
- /**********************************************************************/
-
- extern int dombconnect __ARGS((int argc,char *argv[],void *p));
- #ifdef CALLBOOK
- static int dombcall __ARGS((int argc,char *argv[],void *p));
- #endif
- extern int dodownload __ARGS((int argc,char *argv[],void *p));
- extern int dombupload __ARGS((int argc,char *argv[],void *p));
- extern int dowhat __ARGS((int argc,char *argv[],void *p));
- extern int dozap __ARGS((int argc,char *argv[],void *p));
- static int dosend __ARGS((int argc,char *argv[],void *p));
- extern int dosid __ARGS((int argc,char *argv[],void *p));
- extern int dosysop __ARGS((int argc,char *argv[],void *p));
- extern int dostars __ARGS((int argc,char *argv[],void *p));
- static int dombhelp __ARGS((int argc,char *argv[],void *p));
- static int dombiproute __ARGS((int argc,char *argv[],void *p));
- extern int dombtelnet __ARGS((int argc,char *argv[],void *p));
- extern int dombfinger __ARGS((int argc,char *argv[],void *p));
- static int dombexpert __ARGS((int argc,char *argv[],void *p));
- static int dombjheard __ARGS((int argc,char *argv[],void *p));
- int dombmovemail __ARGS((int argc,char *argv[],void *p));
- void gw_alarm __ARGS((void *p));
- void gw_input __ARGS((int s,void *notused,void *p));
- void gw_superv __ARGS((int null,void *proc,void *p));
- extern int mbx_to __ARGS((int argc,char *argv[],void *p));
- extern int mbx_data __ARGS((struct mbx *m,struct list *cclist,char *extra));
- int msgidcheck __ARGS((char *string));
- extern int thirdparty __ARGS((struct mbx *m));
- #ifdef NETROM
- extern int dombnrnodes __ARGS((int argc,char *argv[],void *p));
- extern int donrneighbour __ARGS((int argc,char *argv[],void *p));
- #endif
-
- static struct cmds DFAR Mbcmds[] = {
- "", doreadnext, 0, 0, NULLCHAR,
- "?", dombhelp, 0, 0, NULLCHAR,
- #ifdef MAILCMDS
- "area", doarea, 0, 0, NULLCHAR,
- #endif
- "bye", domboxbye, 0, 0, NULLCHAR,
- "connect", dombconnect,0, 0, NULLCHAR,
- #ifdef CALLBOOK
- "call", dombcall, 0, 0, NULLCHAR,
- #endif
- #ifdef XMODEM
- "download", dodownload, 0, 2, "D[U|X] <filename>",
- #else
- "download", dodownload, 0, 2, "D[U] <filename>",
- #endif
- "escape", dombescape, 0, 0, NULLCHAR,
- "finger", dombfinger, 0, 0, NULLCHAR,
- "help", dombhelp, 0, 0, NULLCHAR,
- "info", dombhelp, 0, 0, NULLCHAR,
- "iheard", doipheard,0, 0, NULLCHAR,
- "iproute", dombiproute,0, 0, NULLCHAR,
- #ifdef AX25
- "jheard", dombjheard, 0, 0, NULLCHAR,
- #endif
- #ifdef MAILCMDS
- "kill", dodelmsg, 0, 0, NULLCHAR,
- "list", dolistnotes,0, 0, NULLCHAR,
- #endif
- "mboxusers",dombusers, 0, 0, NULLCHAR,
- #ifdef NETROM
- "nodes", dombnrnodes,0, 0, NULLCHAR,
- "nroutes", donrneighbour, 0, 0, NULLCHAR,
- #endif
- "operator", dochat, 0, 0, NULLCHAR,
- "ports", dombports, 0, 0, NULLCHAR,
- #ifdef CALLCLI
- "query", dombcallbook, 0, 2, "Q callsign\nMultiple callsigns allowed per line",
- #endif
- #ifdef MAILCMDS
- "read", doreadmsg, 0, 0, NULLCHAR,
- "send", dosend, 0, 0, NULLCHAR,
- #endif
- "telnet", dombtelnet, 0, 2, "T hostname",
- #ifdef XMODEM
- "upload", dombupload, 0, 2, "U[X] <filename>",
- #else
- "upload", dombupload, 0, 2, NULLCHAR,
- #endif
- #ifdef MAILCMDS
- "verbose", doreadmsg, 0, 0, NULLCHAR,
- #endif
- "what", dowhat, 0, 0, NULLCHAR,
- "xpert", dombexpert, 0, 0, NULLCHAR,
- "zap", dozap, 0, 2, "Z filename",
- #ifdef MAILCMDS
- "[", dosid, 0, 0, NULLCHAR,
- #ifdef AX25
- #ifdef MBFWD
- "f>", dorevfwd, 0, 0, NULLCHAR,
- #endif
- #endif
- #endif
- "@", dosysop, 0, 0, NULLCHAR,
- "***", dostars, 0, 0, NULLCHAR,
- NULLCHAR, NULLFP((int,char**,void*)), 0, 0, "Huh?",
- };
-
- /* "twocmds" defines the MBL/RLI two-letter commands, eg. "SB", "SP" and so on.
- * They have to be treated specially since cmdparse() wants a space between
- * the actual command and its arguments.
- * "SP FOO" is converted to "s foo" and the second command letter is saved
- * in m->stype. Longer commands like "SEND" are unaffected, except for
- * commands starting with "[", i.e. the SID, since we don't know what it will
- * look like.
- */
- static char twocmds[] = "aslrd[muvkx"; /* S,L,R,D,M,U,V,K,X are two-letter commands */
-
- int
- mbx_parse(m)
- struct mbx *m;
- {
- char *cp;
- int i;
- char *newargv[2];
- /* Translate entire buffer to lower case */
- for (cp = m->line; *cp != '\0'; ++cp)
- if(isupper(*cp))
- *cp = tolower(*cp);
- /* Skip any spaces at the begining */
- for(cp = m->line;isspace(*cp);++cp)
- ;
- m->stype = ' ';
- if(*cp != '\0' && *(cp+1) != '\0')
- for(i=0; i<strlen(twocmds); ++i){
- if(*cp == twocmds[i] && (isspace(*(cp+2)) || *(cp+2) == '\0'
- || *cp == '[')){
- if(islower(*(++cp)))
- m->stype = toupper(*cp); /* Save the second character */
- else
- m->stype = *cp;
- *cp = ' ';
- break;
- }
- }
- #ifdef MAILCMDS
- /* See if the input line consists solely of digits */
- cp = m->line;
- for(cp = m->line;isspace(*cp);++cp)
- ;
- newargv[1] = cp;
- for(;*cp != '\0' && isdigit(*cp);++cp)
- ;
- if(*cp == '\0' && strlen(newargv[1]) > 0) {
- newargv[0] = "r";
- return doreadmsg(2,newargv,(void *)m);
- }
- else
- #endif
- return cmdparse(Mbcmds,m->line,(void *)m);
- }
-
- /* This works like recvline(), but telnet options are answered and the
- * terminating newline character is not put into the buffer. If the
- * incoming character equals the value of escape, any queued input is
- * flushed and -2 returned.
- */
- int
- mbxrecvline(m)
- struct mbx *m;
- {
- int s = m->user;
- int escape = m->escape;
- char *buf = m->line;
- int c, cnt = 0, opt, cl;
-
- if(buf == NULLCHAR)
- return 0;
- usflush(Curproc->output);
- #ifdef MBXTDISC
- start_timer(&m->tdisc);
- #endif
- while((c = recvchar(s)) != EOF){
- if(c == IAC){ /* Telnet command escape */
- if((c = recvchar(s)) == EOF)
- break;
- if(c >= 250 && c < 255 && (opt = recvchar(s)) != EOF){
- switch(c){
- case SB:
- opt=recvchar(s); /* Get the real option */
- if(opt==EOF) break;
- cl=opt;
- c=recvchar(s);
- /* Gobble up until we see IAC SE */
- while((c!=EOF) && !(cl==IAC && c==SE)){
- /* maybe check for timeout here, in case someone
- happened to send a binary file with the IAC SB
- sequence in it. */
- cl=c; /* keep track of second last char read */
- c=recvchar(s);
- }
- /* and tell the client where to go... */
- /* tprintf("%c%c%c",IAC,WONT,opt); */
- break;
- case WILL:
- if(opt==TN_LINEMODE){
- m->linemode = 1;
- /* we WANT linemode */
- tprintf("%c%c%c",IAC,DO,opt);
- /* Tell client to do editing */
- tprintf("%c%c%c%c%c%c%c",IAC,SB,TN_LINEMODE,1,1,IAC,SE);
- }
- else{
- tprintf("%c%c%c",IAC,DONT,opt);
- }
- break;
- case WONT:
- tprintf("%c%c%c",IAC,DONT,opt);
- break;
- case DO:
- tprintf("%c%c%c",IAC,WONT,opt);
- break;
- case DONT:
- tprintf("%c%c%c",IAC,WONT,opt);
- }
- /* to be fixed usflush(Curproc->output);*/
- continue;
- }
- if(c != IAC && (c = recvchar(s)) == EOF)
- break;
- }
- /* ordinary character */
- if(c == '\r' || c == '\n')
- break;
- if(uchar(c) == escape){
- if(socklen(s,0)) /* discard any remaining input */
- recv_mbuf(s,NULL,0,NULLCHAR,0);
- cnt = -2;
- break;
- }
- /* Handle <del> chars - from wa7tas */
- if(c == 8) {
- if(cnt > 0) {
- *--buf = 0;
- cnt--;
- }
- } else {
- *buf++ = c;
- ++cnt;
- }
- if(cnt == MBXLINE - 1)
- break;
- }
- if(c == EOF && cnt == 0)
- return -1;
- *buf = '\0';
- #ifdef MBXTDISC
- /* Restart the timeout-timer - WG7J*/
- start_timer(&m->tdisc);
- #endif
- return cnt;
- }
-
- extern void updatedefaults(struct mbx *);
-
- int
- domboxbye(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
-
- m = (struct mbx *)p;
-
- /* for bbs's, just disconnect */
- if(m->sid & MBX_SID)
- return -2;
-
- #ifdef USERLOG
- setlastread(m);
- updatedefaults(m);
- #endif
- /* Now say goodbye */
- tprintf("\nThank you %s,\nfor calling the %s NOS Tcp/Ip Mailbox.\n\n",m->name,
- Hostname);
- #ifdef ALLSERV
- if(m->type == TIP_LINK)
- tputs("Please hang up now.\n");
- #endif
- usflush(m->user);
- return -2; /* signal that exitbbs() should be called */
- }
-
- static int
- dombhelp(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[255];
- int i;
- FILE *fp;
- if(*argv[0] == '?') {
- tputs(Longmenu);
- return 0;
- }
- buf[0] = '\0';
- if(argc > 1)
- for(i=0; Mbcmds[i].name != NULLCHAR; ++i)
- if(!strncmp(Mbcmds[i].name,argv[1],strlen(argv[1]))) {
- sprintf(buf,"%s/%s.hlp",Helpdir,Mbcmds[i].name);
- break;
- }
- if(buf[0] == '\0')
- if(*argv[0] == 'i') {
- /* INFO command */
- tprintf(Nosversion,Version);
- sprintf(buf,"%s/info.hlp",Helpdir);
- } else
- sprintf(buf,"%s/help.hlp",Helpdir);
- if((fp = fopen(buf,READ_TEXT)) != NULLFILE) {
- sendfile(fp,Curproc->output,ASCII_TYPE,0);
- fclose(fp);
- } else {
- if(*argv[0]!='i')
- tputs("No help available.\n");
- }
- return 0;
- }
-
- extern void dumproute __ARGS((struct route *rp,char *p));
- extern char RouteHeader[];
-
- /* Show non-private routes only */
- int
- dombiproute(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- register int i,bits;
- register struct route *rp;
- char buf[85];
-
- tputs(RouteHeader);
- for(bits=31;bits>=0;bits--){
- for(i=0;i<HASHMOD;i++){
- for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
- if(!(rp->flags & RTPRIVATE)) {
- dumproute(rp,buf);
- if(tprintf("%s\n",&buf[4]) == EOF)
- return 0;
- }
- }
- }
- }
- if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)) {
- dumproute(&R_default,buf);
- if(tprintf("%s\n",&buf[4]) == EOF)
- return 0;
- }
- return 0;
- }
-
- #ifdef MAILCMDS
-
- extern char Badmsg[];
- extern char Nomail[];
-
- /* Move messages from current area to another */
- int
- dombmovemail(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int num,i;
- int move[NARG];
- char *to;
- struct mbx *m;
- char buf[MBXLINE];
- #ifdef notdef
- char *cp;
- #endif
- FILE * Mfile; /* file to move to */
- struct let *cmsg;
- long size;
- int thisone;
-
- m = (struct mbx *)p;
-
- if(argc == 1) {
- tputs("Syntax: MM area - moves current message\n"
- " MM n1 [n2...] area - move message n1 (n2...)\n");
- return 0;
- }
- if(m->mfile == NULLFILE) {
- tputs(Nomail);
- return 0;
- }
- if(argc == 2) {
- /* NO message #, use current message */
- num = 1;
- to = argv[1];
- move[0] = m->current;
- } else {
- /* Scan all message # to move */
- num=0;
- for(i=1;i<argc-1;i++) {
- if( (move[num]=atoi(argv[i])) != 0 ) {
- if(move[num] <= m->nmsgs)
- num++;
- } else
- tprintf(Badmsg,argv[i]);
- }
- to = argv[argc-1];
- }
- #ifdef notdef
- /* translate '.' and '\\' to '/' */
- for(cp=to;*cp!='\0';cp++)
- if((*cp == '.') || (*cp == '\\'))
- *cp = '/';
- #endif
-
- /* Now try to lock the destination file */
- if(mlock(Mailspool,to) == -1) {
- tprintf("Can't lock '%s', please try later\n",to);
- return 0;
- }
- /* open the destination file for appending */
- sprintf(buf,"%s/%s.txt",Mailspool,to);
- if((Mfile=fopen(buf,"a")) == NULLFILE) {
- tprintf("Can't open '%s'\n",buf);
- rmlock(Mailspool,to);
- return 0;
- }
- /* Okay, let's do the work */
- for(i=0;i<num;i++) {
- thisone = move[i];
- cmsg = &m->mbox[thisone];
- /* find start of this message */
- fseek(m->mfile,cmsg->start,0);
- size = cmsg->size;
- /* now read this message */
- while(size > 0 && fgets(buf,MBXLINE,m->mfile)!= NULLCHAR) {
- fputs(buf,Mfile);
- size -= strlen(buf);
- }
- /* delete this message */
- cmsg->status |= BM_DELETE;
- m->change = 1;
- tprintf("Message %d moved...\n",thisone);
- }
- fclose(Mfile);
- rmlock(Mailspool,to);
- return 0;
- }
- #endif
-
- static int
- dombexpert(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
-
- m = (struct mbx *)p;
-
- switch(m->stype) {
- case 'M':
- if(argc == 1)
- tprintf("-more- after %d lines\n",m->morerows);
- else {
- m->morerows = atoi(argv[1]);
- }
- break;
- case 'A':
- m->sid ^= MBX_AREA;
- break;
- case 'N':
- m->sid ^= MBX_NRID;
- break;
- default:
- m->sid ^= MBX_EXPERT;
- break;
- }
- return 0;
- }
-
- extern char SysopBusy[];
-
- static int
- dochat(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char buf[8], *newargv[3];
- struct mbx *m;
-
- m = (struct mbx *)p;
-
- if(MAttended){
- m->state = MBX_CHAT;
- newargv[0] = "C";
- newargv[1] = Hostname;
- sprintf(buf,"%d",IPPORT_TTYLINK);
- newargv[2] = buf;
- return dombtelnet(3,newargv,p);
- }
- else {
- tputs(SysopBusy);
- }
- /* It returns only after a disconnect or refusal */
- return 0;
- }
-
- #ifdef AX25
- static int
- dombjheard(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct iface *ifp;
- struct mbx *m = (struct mbx *)p;
-
- if(argc > 1){
- if( ((ifp = if_lookup(argv[1])) == NULLIF) || (ifp->type != CL_AX25) ||
- ((ifp->flags & HIDE_PORT) && !(m->privs & MBX_SYSOP)) ) {
- tprintf(Badinterface,argv[1]);
- return 0;
- }
- axheard(ifp);
- return 0;
- }
- for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next){
- if((ifp->flags & LOG_AXHEARD) && ( !(ifp->flags & HIDE_PORT) || m->privs&MBX_SYSOP) )
- if(axheard(ifp) == EOF)
- break;
- }
- return 0;
- }
- #endif
-
- #ifdef CALLBOOK
- extern char *InetCallserver;
- extern char *InetCallserverport;
-
- /*This is a simple way of estiblishing a connection
- *to a callbook-server via tcp - WG7J
- */
- static int
- dombcall(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- char *newargv[3];
-
- if(InetCallserver!=NULLCHAR){
- newargv[0] = "C";
- newargv[1] = InetCallserver;
- newargv[2] = InetCallserverport;
- return dombtelnet(3,newargv,p);
- }
- else {
- tputs("Internet callserver not configured\n");
- }
- /* It returns only after a disconnect or refusal */
- return 0;
- }
-
- #endif /*CALLBOOK*/
-
- #ifdef CALLCLI
- static int
- dombcallbook(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- struct mbx *m;
- char buf[8], *newargv[3];
- extern char *Callserver;
- int req, ret = 0;
-
- m = (struct mbx *) p;
- /* tprintf("Looking up - %s - in the callbook at %s\n",argv[1],Callserver);*/
- sprintf(buf,"%d",IPPORT_CALLDB);
- newargv[0] = "C";
- newargv[1] = Callserver;
- newargv[2] = buf;
-
- for (req = 1; req < argc; req++) {
- if (argv[req] == NULLCHAR) return ret;
- m->startmsg = mallocw(80); /* is freed each time by gw_connect() */
- sprintf(m->startmsg,"%s\n", argv[req]);
- log(m->user, "%s checking callbook: %s",m->name,argv[req]);
- tprintf("Looking for \" %s \" in the callbook at %s\n",argv[req],Callserver);
- ret = dombtelnet(3,newargv,p);
- }
- return ret; /* It looks like all possible returns are zero anyway! */
- }
- #endif
-
- #ifdef MAILCMDS
-
- extern int Mbloophold;
-
- /*Some additional security - WG7J
- *NO_3PARTY = disallow all 3rd party mail
- *NO_SENDCMD = only allow mail to sysop
- */
- extern int NoBid;
-
- static int
- dosend(argc,argv,p)
- int argc;
- char *argv[];
- void *p;
- {
- int cccnt = 0, fail = 0;
- char *host, *cp, fullfrom[MBXLINE], sigwork[LINELEN], *rhdr = NULLCHAR;
- struct list *ap, *cclist = NULLLIST;
- struct mbx *m;
- FILE *fp;
- #ifdef notdef
- time_t now;
- #endif
- int done = 0;
- char *cp2;
- int c;
-
- #ifdef RLINE
- struct tm t;
- #define ODLEN 16
- #define OBLEN 32
- char tmpline[MBXLINE];
- char fwdbbs[NUMFWDBBS][FWDBBSLEN+1];
- int myfwds = 0;
- int i;
- int zulu;
- int check_r = 0;
- int found_r = 0;
- char origdate[ODLEN];
- char origbbs[OBLEN];
- int loops = 0;
- char Me[15];
-
- origdate[0] = '\0';
- origbbs[0] = '\0';
- #endif
-
- m = (struct mbx *)p;
-
- if((m->stype != 'R' || (m->sid & MBX_SID)) && mbx_to(argc,argv,m)
- == -1){
- tputs((m->sid & MBX_SID) ? "NO - syntax error\n" : \
- "S command syntax error - format is:\n" \
- "S[C|F] name [@ host] [< from_addr] [$bulletin_id]\n" \
- "SR [number]\n");
- mail_error("%s: MBOX S syntax error - %s\n",m->name,m->line);
- return 0;
- }
-
- /*Check for send permission */
- if(m->privs & NO_SENDCMD) { /*is this to 'SYSOP' or 'sysop' ?*/
- if(stricmp(m->to,"sysop")) {
- tputs((m->sid & MBX_SID) ? "NO - permission denied\n" : \
- "Sorry, only mail to 'sysop' allowed!\n");
- mail_error("%s: no mail permission - %s\n",m->name,m->to);
- return 0;
- }
- }
- /* Check for a BID on bulletins from other bbs's - WG7J */
- if((m->sid & MBX_SID) && !NoBid &&
- (m->stype == 'B') && (m->tomsgid == NULLCHAR)) {
- tputs("NO - No BID!\n");
- log(m->user,"%s: SB without BID - %s",m->name,m->to);
- mail_error("%s: SB without BID - %s",m->name,m->to);
- return 0;
- }
-
- if(m->stype != 'R' && msgidcheck(m->tomsgid)) {
- if(m->sid & MBX_SID)
- tputs("NO - ");
- tprintf("Already have %s\n",m->tomsgid);
- return 0;
- }
- if(m->stype == 'R' && !(m->sid & MBX_SID) &&
- mbx_reply(argc,argv,m,&cclist,&rhdr) == -1)
- return 0;
- if((cp = rewrite_address(m->to)) != NULLCHAR)
- if(strcmp(m->to,cp) != 0){
- m->origto = m->to;
- m->to = cp;
- }
- else
- free(cp);
-
- /* refuse any mail that gets rewritten into 'refuse' - WG7J */
- if(!strcmp(m->to,"refuse")) {
- tputs((m->sid & MBX_SID) ? "NO - refused\n" : \
- "Bad user or hostname, please mail 'sysop' for help\n");
- return 0;
- }
-
- if( (!ThirdParty && !(m->privs & SYSOP_CMD)) || (m->privs & NO_3PARTY) )
- if(thirdparty(m) == 0){
- tputs(Mbwarning);
- mail_error("%s: 3rd party mail refused - %s\n",m->name,m->to);
- return 0;
- }
-
- /* Send the new 'To:' line to sysops only - WG7J */
- if((m->privs&SYSOP_CMD) && (m->origto != NULLCHAR || m->stype == 'R') \
- && !(m->sid & MBX_SID))
- tprintf("To: %s\n", m->to);
- if(validate_address(m->to) == 0){
- tputs((m->sid & MBX_SID) ? "NO - bad address\n" : \
- "Bad user or hostname, please mail 'sysop' for help\n");
- free(rhdr);
- del_list(cclist);
- /* We don't free any more buffers here. They are freed upon
- * the next call to mbx_to() or to domboxbye()
- */
- return 0;
- }
- /* Display the Cc: line (during SR command) */
- for(ap = cclist; ap != NULLLIST; ap = ap->next) {
- if(cccnt == 0){
- tprintf("%s",Hdrs[CC]);
- cccnt = 4;
- }
- else {
- tputs(", ");
- cccnt += 2;
- }
- if(cccnt + strlen(ap->val) > 80 - 3) {
- tputs("\n ");
- cccnt = 4;
- }
- tputs(ap->val);
- cccnt += strlen(ap->val);
- }
- if(cccnt)
- tputc('\n');
-
- /* If the the command was 'SC' then read the Cc: list now - WG7J */
- if((m->stype == 'C') && !(m->sid & MBX_SID)) {
- m->stype = 'P'; /* make everything private */
- tputs(CcLine);
- if(mbxrecvline(m) != -1) {
- if(strlen(m->line)) {
- if(*m->line == 0x01) { /* CTRL-A, abort */
- free(rhdr);
- del_list(cclist);
- tputs(MsgAborted);
- return 0;
- }
- cp = m->line;
- /* get all the Cc addresses, separated by comma's */
- while((cp2=strchr(cp,',')) != NULLCHAR) {
- *cp2 = '\0';
- /*get rid of leading spaces or tabs*/
- while(*cp == ' ' || *cp == '\t')
- cp++;
- if(strlen(cp))
- addlist(&cclist,cp,0);
- cp = cp2 + 1;
- }
- /* Do the last or only one */
- /* get rid of leading spaces or tabs*/
- while(*cp == ' ' || *cp == '\t')
- cp++;
- if(strlen(cp))
- addlist(&cclist,cp,0);
- }
- } else {
- free(rhdr);
- del_list(cclist);
- return 0;
- }
- }
-
- /* Now check to make sure we can create the needed tempfiles - WG7J */
- if((m->tfile = tmpfile()) == NULLFILE) {
- free(rhdr);
- del_list(cclist);
- /*
- tputs((m->sid & MBX_SID) ? "NO - no temp file\n" : \
- "Can't create temp file for mail\n");
- return 0;
- */
- /* instead of saying NO and have the other bbs think we already
- * have the message, disconnect !
- */
- if(m->sid & MBX_SID)
- return -2;
- /* tell regualr users about it */
- tputs("Can't create temp file for mail\n");
- return 0;
- }
- #ifdef RLINE
- /* Only accept R: lines from bbs's */
- if((m->sid & MBX_SID)&&(Rdate || Rreturn || Rfwdcheck || Mbloophold)){
- /* Going to interpret R:headers,
- * we need another tempfile !
- */
- if((m->tfp = tmpfile()) == NULLFILE) {
- free(rhdr);
- del_list(cclist);
- /*
- tputs("NO - no temp file\n");
- return 0;
- */
- /* disconnect to avoid the other bbs to think that we already have
- * the message !
- */
- return -2;
- }
- /* Now we got enough :-) */
- check_r = 1;
- Checklock++;
- /* Set the call, used in loop detect code - WG7J */
- if(Mbloophold) {
- pax25(Me,Mycall);
- if((cp = strchr(Me,'-')) != NULLCHAR)
- *cp = '\0'; /* remove SSID */
- }
- }
- #endif
-
- m->state = MBX_SUBJ;
- if(m->stype != 'R' || (m->sid & MBX_SID)) {
- /* This might bollix incoming forwarding, we'll see: suggested by
- N6NKO in mail that \n after Subject: become a space. Brandon */
- tputs((m->sid & MBX_SID) ? "OK\n" : "Subject: ");
- if(mbxrecvline(m) == -1) {
- #ifdef RLINE
- if(check_r) {
- MYFCLOSE(m->tfp);
- Checklock--;
- }
- #endif
- return 0;
- }
- }
- else /* Replying to a message */
- tprintf("Subject: %s\n",m->line);
-
- m->subject = strdup(m->line);
-
- #ifdef RLINE
- if(!check_r) {
- #endif
- mbx_data(m,cclist,rhdr);
- /*Finish smtp headers*/
- fprintf(m->tfile,"\n");
- #ifdef RLINE
- }
- #endif
- free(rhdr);
- m->state = MBX_DATA;
- if(!(m->sid & MBX_SID) && m->stype != 'F')
- tprintf("Enter message. %s",Howtoend);
-
- if(m->stype != 'F' || (m->sid & MBX_SID) != 0) {
- while(mbxrecvline(m) != -1){
- if(m->line[0] == 0x01){ /* CTRL-A */
- MYFCLOSE(m->tfile);
- #ifdef RLINE
- if(check_r)
- MYFCLOSE(m->tfp);
- #endif
- tputs(MsgAborted);
- del_list(cclist);
- return 0;
- }
- if(m->line[0] != CTLZ && stricmp(m->line, "/ex")) {
- #ifdef RLINE
- if(check_r) {
- /* Check for R: lines to start with */
- if(!strncmp(m->line,"R:",2)) { /*found one*/
- found_r = 1;
- /*Write this line to the second tempfile
- *for later rewriting to the real one
- */
- fprintf(m->tfp,"%s\n",m->line);
- /* Find the '@[:]CALL.STATE.COUNTRY'or
- * or the '?[:]CALL.STATE.COUNTRY' string
- * The : is optional.
- */
- if( ((cp=strchr(m->line,'@')) != NULLCHAR) ||
- ((cp=strchr(m->line,'?')) != NULLCHAR) ) {
- if((cp2=strchr(cp,' ')) != NULLCHAR)
- *cp2 = '\0';
- if((cp2=strchr(cp,'\n')) != NULLCHAR)
- *cp2 = '\0';
- if((cp2=strchr(cp,'\t')) != NULLCHAR)
- *cp2 = '\0';
- /* Some bbs's send @bbs instead of @:bbs*/
- if (*++cp == ':')
- cp++;
- /* if we use 'return addres'
- * copy whole 'domain' name
- */
- if(Rreturn)
- if(strlen(cp) <= OBLEN)
- strcpy(origbbs,cp);
- /* Optimize forwarding ? */
- if(Rfwdcheck || Mbloophold) {
- /*if there is a HADDRESS, cut off after '.'*/
- if((cp2=strchr(cp,'.')) != NULLCHAR)
- *cp2 = '\0';
- if(Mbloophold)
- /* check to see if this is my call ! */
- if(!stricmp(Me,cp))
- loops++;
- /*cross-check with MyFwds list*/
- if(Rfwdcheck) {
- for(i=0;i<Numfwds;i++) {
- if(!strcmp(MyFwds[i],cp)) {
- /*Found one !*/
- strcpy(fwdbbs[myfwds++],cp);
- break;
- }
- }
- }
- }
- }
- if(Rdate) {
- /* Find the 'R:yymmdd/hhmmz' string */
- if((cp=strchr(m->line,' ')) != NULLCHAR) {
- *cp = '\0';
- if(strlen(m->line+2) <= ODLEN)
- strcpy(origdate,m->line+2);
- }
- }
- } else {
- /* The previous line was last R: line
- * so we're done checking
- * now write the smtp headers and
- * all saved R: lines to the right tempfile
- */
- check_r = 0;
- Checklock--;
- /*Did we actually find one ?*/
- if(found_r) {
- if(Rreturn)
- m->origbbs = strdup(strlwr(origbbs));
- if(Rdate) {
- if((cp=strchr(origdate,'/')) != NULLCHAR) {
- zulu = 0; /* not initialized before! */
- if((*(cp+5) == 'z') || (*(cp+5) == 'Z')) {
- *(cp+5) = '\0';
- zulu = 1;
- }
- t.tm_min = atoi(cp+3);
- *(cp+3) = '\0';
- t.tm_hour = atoi(cp+1);
- *cp = '\0';
- t.tm_mday = atoi(&origdate[4]);
- origdate[4] = '\0';
- t.tm_mon = (atoi(&origdate[2]) - 1);
- origdate[2] = '\0';
- t.tm_year = atoi(origdate);
- /* Set the date in rfc 822 format */
- m->date = mallocw(40);
- sprintf(m->date,"%.2d %s %02d %02d:%02d:00 %.3s\n",
- t.tm_mday,
- Months[t.tm_mon],
- t.tm_year,
- t.tm_hour,
- t.tm_min,
- zulu ? "UTC" : "");
- }
- }
- }
- /* Now write the headers,
- * possibly adding Xforwarded lines for bulletins,
- * or anything that has a BID.
- * Add the X-Forwarded lines and loop detect
- * headers FIRST,
- * this speeds up forwarding...
- */
- if(Mbloophold && loops >= Mbloophold)
- fprintf(m->tfile,"%sLoop\n",Hdrs[XBBSHOLD]);
- if(Rfwdcheck && found_r && \
- ((m->stype == 'B') || (m->tomsgid)) ){
- /*write Xforwarded headers*/
- for(i=0;i<myfwds;i++) {
- fprintf(m->tfile,"%s%s\n",Hdrs[XFORWARD],fwdbbs[i]);
- }
- }
- /*write regular headers*/
- mbx_data(m,cclist,rhdr);
- /* Finish smtp headers */
- fprintf(m->tfile,"\n");
-
- /* Now copy the R: lines back */
- if(found_r) {
- rewind(m->tfp);
- while(fgets(tmpline,sizeof(tmpline),m->tfp)!=NULLCHAR)
- fputs(tmpline,m->tfile);
- }
- MYFCLOSE(m->tfp);
-
- /* And add this first non-R: line */
- fprintf(m->tfile,"%s\n",m->line);
- }
- } else
- #endif
- fprintf(m->tfile,"%s\n",m->line);
- } else {
- #ifdef RLINE
- if(check_r) {
- /* Hmm, this means we never finished the R: headers
- * tmp file still open !
- */
- MYFCLOSE(m->tfp);
- }
- #endif
- done = 1; /* To indicate the difference between
- * mbxrecvline() returning -1 and /ex ! - WG7J
- * Now also used to indicate if the message should
- * be sent or not !
- */
- /* Now ask users if they want to send this ! - WG7J */
- if( Mbsendquery && !(m->sid & MBX_SID)) {
- if(m->type == TELNET_LINK || m->type == TIP_LINK)
- c = tkeywait("Send(N=no)?",0,m->linemode);
- else /* For AX.25 and NET/ROM connects */
- c = mykeywait("Send(N=no)?",m);
- if(c == -1 || c == 'n' || c == 'N') {
- done = 0; /* signal delete of message */
- tputs(MsgAborted);
- }
- }
- break; /* all done */
- }
- }
- if(!done) {
- /* We did NOT get ^Z or /EX, but mbxrecvline returned -1 !!!
- * This means the connection is gone ! - WG7J
- * Now can also mean that the user doesn't want to send msg !
- */
- MYFCLOSE(m->tfile);
- #ifdef RLINE
- if(check_r)
- MYFCLOSE(m->tfp);
- #endif
- del_list(cclist);
- free(rhdr); /*Just in case*/
- return 0;
- }
- } else {
- fprintf(m->tfile,"----- Forwarded message -----\n\n");
- msgtofile(m,m->current,m->tfile,0);
- fprintf(m->tfile,"----- End of forwarded message -----\n");
- }
-
- /* Insert customised signature if one is found */
- if(!(m->sid & MBX_SID)) { /* not a forwarding BBS */
- sprintf(sigwork,"%s/%s.sig",Signature,
- m->tofrom ? m->tofrom : m->name);
- if((fp = fopen(sigwork,READ_TEXT)) != NULLFILE){
- while(fgets(sigwork,LINELEN,fp) != NULLCHAR)
- fputs(sigwork,m->tfile);
- fclose(fp);
- }
- }
-
- if((host = strrchr(m->to,'@')) == NULLCHAR) {
- host = Hostname; /* use our hostname */
- if(m->origto != NULLCHAR) {
- /* rewrite_address() will be called again by our
- * SMTP server, so revert to the original address.
- */
- free(m->to);
- m->to = m->origto;
- m->origto = NULLCHAR;
- }
- }
- else
- host++; /* use the host part of address */
-
- /* make up full from name for work file */
- if(m->tofrom != NULLCHAR)
- sprintf(fullfrom,"%s%%%s@%s",m->tofrom, m->name, Hostname);
- else
- sprintf(fullfrom,"%s@%s",m->name,Hostname);
- if(cclist != NULLLIST && stricmp(host,Hostname) != 0) {
- fseek(m->tfile,0L,0); /* reset to beginning */
- fail = queuejob(m->tfile,Hostname,cclist,fullfrom);
- del_list(cclist);
- cclist = NULLLIST;
- }
- addlist(&cclist,m->to,0);
- fseek(m->tfile,0L,0);
- fail += queuejob(m->tfile,host,cclist,fullfrom);
- del_list(cclist);
- MYFCLOSE(m->tfile);
- if(fail){
- if(!(m->sid & MBX_SID)) /* only when we're not a bbs */
- tputs("Couldn't queue msg!\n");
- } else {
- if(m->sid & MBX_SID)
- MbRecvd++;
- else {
- tputs("Msg queued\n");
- MbSent++;
- }
- #ifdef notdef
- /* BID is now saved in the smtp server ! - WG7J */
- if(m->tomsgid != NULLCHAR && \
- (fp = fopen(Historyfile,APPEND_TEXT)) != NULLFILE) {
- /* Timestamp added to allow automatic expiry of bid file - WG7J */
- time(&now);
- fprintf(fp,"%s %ld\n",m->tomsgid,now); /* Save BID */
- fclose(fp);
- }
- #endif
- }
- smtptick(NULL); /* wake SMTP to send that mail */
- return 0;
- }
- #endif /* MAILCMDS */
-
- #endif /* MAILBOX */
-